package com.CampaignManager.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.CampaignManager.shared.CampaignService;
import com.CampaignManager.shared.CampaignServiceAsync;
import com.CampaignManager.shared.CityDTO;
import com.CampaignManager.shared.JobDTO;
import com.CampaignManager.shared.NotLoggedInException;
import com.CampaignManager.shared.PlayerCityDTO;
import com.CampaignManager.shared.PlayerDTO;
import com.CampaignManager.shared.ResourceAmountDTO;
import com.CampaignManager.shared.UnitTypeDTO;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.Maps;
import com.google.gwt.maps.client.control.LargeMapControl;
import com.google.gwt.maps.client.event.MapClickHandler;
import com.google.gwt.maps.client.event.MapClickHandler.MapClickEvent;
import com.google.gwt.maps.client.event.MapInfoWindowBeforeCloseHandler;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.event.MarkerDragEndHandler;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.maps.client.geom.Size;
import com.google.gwt.maps.client.overlay.GroundOverlay;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class CampaignManager implements EntryPoint {
	
	private MainPage mainPage = null;
	private MapWidget map = null;
	private PlayerDTO playerInfo = null;
	private Marker currentplayerMarker = null;
	private Marker playerDestMarker = null;
	private TextOverlay playerDestText = null;
	
	public boolean isAddingCity = false; 
	
	public CityDTO[] Cities = null;
	public List<PlayerDTO> Players = new ArrayList<PlayerDTO>();
		
	public final CampaignServiceAsync campaignService = GWT.create(CampaignService.class);
			
	public void onModuleLoad() {
					    
	    campaignService.login(GWT.getHostPageBaseURL(), new AsyncCallback<PlayerDTO[]>() {
	    	public void onFailure(Throwable error) {
	    		handleError(error);
	    	}

	    	public void onSuccess(PlayerDTO[] result) {	    		
	    		for (PlayerDTO p : result) {
	    			Players.add(p);
	    			if (p.isCurrentPlayer())
	    				playerInfo = p;
	    		}
	    		loadMainPage();	    		
	    	}
    	});
    }

	private void loadMainPage() {
		
		mainPage = new MainPage(this);
		RootLayoutPanel.get().add(mainPage);
			
		Maps.loadMapsApi("ABQIAAAAtG8bUH-EavnpvRzCrS9bzhRiR7MBcpZA3DdLbbgDExr8bUuRbxS6WAdnbuHQooFM9GyV0_aKociZkw", "2", false, new Runnable() {
			public void run() {								
				mapApiRun();	
			}			
		});
	}

	private void mapApiRun() {
		
		LatLng mapCenter = LatLng.newInstance(19.394067895396613, -100.37109375);		
		map = new MapWidget(mapCenter, 5);

	    map.setScrollWheelZoomEnabled(true);
	    
	    // Add some controls for the zoom level
	    map.addControl(new LargeMapControl());
	    
	    map.addMapClickHandler(new MapClickHandler() {
          public void onClick(MapClickEvent e) {
            mapClicked(e);
          }				
        });
	    
	    LatLng bottomLeft = LatLng.newInstance(-75, -180);
		LatLng topRight = LatLng.newInstance(75, -25);
		LatLngBounds bounds = LatLngBounds.newInstance(bottomLeft,topRight);
	    GroundOverlay x = new GroundOverlay("Images/WesternImmoren-Color.jpg", bounds);			    
	    map.addOverlay(x);
    	
	    this.showMap();
		
		if (playerInfo == null) {
			characterCreation();
		} else {
			LoadCharacterInfo();
		}
	}
		
	private void characterCreation() {
						
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
		dialogbox.setText("Welcome to Game of Throne & Blade: Warmachine!");
	    
	    String html = "<BR>Like Game of Thrones this region is rife with rival houses vying for power through politics, espionage or all out war.";
	    html += "<BR><BR>";
	    html += "Like Mount & Blade (and real life) this is not a game that you 'win'.  Your goals and how you achieve them are of your own making. Rewards are set based on the difficulty of what you do, but what you choose to do and and why is up to you.";
	    html += "<BR><BR>";
	    html += "Like Warmachine it all takes place in the Iron Kingdoms. Created by Privateer Press over years of making various games, it is an immersive world with history, lore, characters and an ongoing plot making the perfect setting for an adventure we invent.<BR>";
	    HTML message = new HTML(html);
	    
	    Button button = new Button("Next");
	    button.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	dialogbox.hide();
	        	characterCreationStep2();
	        }
        });
	    SimplePanel holder = new SimplePanel();
	    holder.add(button);
	    DialogBoxContents.add(message);
	    DialogBoxContents.add(holder);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();
	}
	private void characterCreationStep2() {
		
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
	    dialogbox.setText("Create your character");
	    
	    String namePromptString = "Give your character a name.<BR><BR>";
	    HTML namePromptHtml = new HTML(namePromptString);
	    		    
	    HorizontalPanel nameArea = new HorizontalPanel();
	    Label nameLabel = new Label("Full Name: ");
	    final TextBox nameTextbox = new TextBox();
	    nameArea.add(nameLabel);
	    nameArea.add(nameTextbox);
	    
	    String html = "<BR>What kind of person are you in this world?  Are you a gold grubbing merc, a mindless bloodthirsty warmonger, perhaps a weasley plotting politician?";
	    html += "<BR><BR>";
	    html += "&nbsp &nbsp &nbsp Don't think of it like an english assignment, just put as little as you want saying who you are and what makes you tick.  Be creative, and don't create a character like you in real life.  The goal is to create an interesting story with the character, not to make the character successful, so don't be afraid to create a character very different from yourself, even if it is self-destructive or severely flawed.<BR><BR>";
	    HTML message = new HTML(html);

	    final TextArea input = new TextArea();
	    input.setWidth("100%");
	    
	    Button button = new Button("Next");
	    button.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	if (nameTextbox.getText() == null) {
	        		Window.alert("Character name is Required");
	        	} else if (input.getText() == null) {
	        		Window.alert("Character description is Required");
	        	} else {
	        		dialogbox.hide();
	        		characterCreationStep3(nameTextbox.getText(),input.getText());
	        	}
	        }
        });
	       	    
	    DialogBoxContents.add(namePromptHtml);
	    DialogBoxContents.add(nameArea);
	    DialogBoxContents.add(message);
	    DialogBoxContents.add(input);
	    DialogBoxContents.add(button);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();
	}
	private void characterCreationStep3(final String name, final String desc) {
		
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
	    dialogbox.setText("Where are you now?");
	    
	    String html = "<BR>You can fill in backstory of your character better as you become more familiar with the Iron Kingdoms.  As you fill in your backstory and describe your ongoing undertakings you will earn narration points which will allow you to do more and more interesting things with your character.  For now though, just pick where your character is:";
	    html += "<BR><BR>";
	    HTML message = new HTML(html);

	    FlexTable buttonGrid = new FlexTable();
	    	    
	    ClickHandler clicky = new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	dialogbox.hide();
	        	characterCreationStep4(name,desc,((Button)event.getSource()).getText());	        	
	        }
        };
        
        Button cygnarButton = new Button("Cygnar");
	    cygnarButton.addClickHandler(clicky);
	    buttonGrid.setWidget(0, 0, cygnarButton);
	    
	    Button khadorButton = new Button("Khador");
	    khadorButton.addClickHandler(clicky);
	    buttonGrid.setWidget(0, 1, khadorButton);
	    
	    Button ordButton = new Button("Ord");
	    ordButton.addClickHandler(clicky);
	    buttonGrid.setWidget(1, 0, ordButton);
	    
	    Button llaelButton = new Button("Llael");
	    llaelButton.addClickHandler(clicky);
	    buttonGrid.setWidget(1, 1, llaelButton);
	    
	    DialogBoxContents.add(message);
	    DialogBoxContents.add(buttonGrid);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();		
	}
	private void characterCreationStep4(final String name, final String desc, final String faction) {
		
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
		dialogbox.setText(faction);
	    
	    String html = "<BR>";
		
		if (faction.equals("Cygnar")) {			
			html += "South of Ord and Llael is the mighty nation of Cygnar, long Khador's hated enemy.  Cygnar is a large kingdom and one particularly rich in resources and fertile lands.  Accordingly it boasts the largest population and one of the mightiest militaries in western Immoren. It holds the southern peninsula along the Broken Coast and thereby has the longest stretch of shoreline of any of the Iron Kingdoms, with a powerful navy to match.  As large as the kingdom appears on a map, it is worth noting how much of its southern and western lands are covered by the dense mountains of the Wyrmwall, uncivilized and treacherous peaks never tamed by man.";
			html += "<BR>";
			html += "&nbsp &nbsp &nbsp Cygnar views themselves as the good guys of Warmachine.  It is a sprawling kingdom that is surrounded on all sides by enemies.  Cygnar is technologically advanced and uses a lightning theme.";
		} else if (faction.equals("Khador")) {
			html += "In the north stands the vast nation of Khador, its lands noted mostly for the frozen bite of its ice-encased mountains and less for the milder plains, rivers, lakes, farmland, and hills of its southern expanses. A few years ago Khador declared itself an empire and has occupied the western half of neighboring Llael.  Khadorans have a long history as warriors and conquerors, having arisen to dominate any rivals they encountered as well as their rugged land.";
			html += "<BR>";
			html += "&nbsp &nbsp &nbsp Khador is an ancient empire that is themed after tsarist Russia that is seeking to reclaim their glory and territory.  Khador uses a cold theme.";
		} else if (faction.equals("Ord")) {
			html += "In the west is Ord, significant only if you were born there.  It is a small kingdom boasting hardy people but not blessed with an abundance of resources. Ord is a land of fog-shrouded moors, imposing hills, and a stretch of coastline where their proud ports seek to dominate the seas.";
			html += "<BR>";
			html += "&nbsp &nbsp &nbsp Ord is the base of operations for the international crime syndicate called the The Four Star Syndicate. Mercenary units from that Contract will be available to you here.";
		} else if (faction.equals("Llael")) {
			html += "Northeast of Ord and south of Rhul was Llael, once famed for its vineyards and clever merchants but recently fallen to foreign invasion.  Llael has been swallowed up by Khador, churned by the boots of Cygnaran soldiers and exploited by zealots of the Protectorate of Menoth.  Some few Llaelese resist their occupiers, and there are those who still dream of freedom.";
			html += "<BR>";
			html += "&nbsp &nbsp &nbsp Llaels military comes in the form of the mercenary army The Highborn Covenant.  Mercenary units from that Contract will be available to you here.";
		}
		html += "<BR><BR>";
		HTML message = new HTML(html);
		
		final Button button = new Button("Next");
	    button.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	button.setEnabled(false);
	        	button.setText("Creating character...");
	        	campaignService.CreateNewPlayer(GWT.getHostPageBaseURL(), name,desc,faction,new AsyncCallback<PlayerDTO>() {
	    			public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(PlayerDTO p) {	    				
	    				dialogbox.hide();
	    				playerInfo = p;
	    				Players.add(p);
	    				LoadCharacterInfo();
	    			}
	    		});
	        }
        });
	    
		DialogBoxContents.add(message);
	    DialogBoxContents.add(button);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();	
	}

	private void LoadCharacterInfo() {
		
		mainPage.welcomeLabel.setText("Welcome " + playerInfo.getCharacterName());
		mainPage.signoutAnchor.setHref(playerInfo.getLogoutUrl());
				
		if (playerInfo.isAdmin()) {
			mainPage.northPanel.add(new Label("(admin)"));
			mainPage.btnAddCity.setVisible(true);
			mainPage.btnPrimeData.setVisible(true);
		}
		addPlayerMarker();
		
		if (!playerInfo.isDoneMapTutorial()) {
			mapTutorial();
		} else {
			//if (CalendarUtil.getDaysBetween(playerInfo.getLastForageDate(),  new Date()) >= 1) 
			//	CreateForageResource();
			LoadCityMarkers();			
		}
		
		Timer t = new Timer() {
			
			@Override
			public void run() {
				UpdatePlayerMarker();			
			}
		};
		t.scheduleRepeating(1000);		
	}
	
	private void addPlayerMarker() {
		
		final CampaignManager finalThis = this;
		
		for (final PlayerDTO p : Players) {
		
			Icon icon = Icon.newInstance();
			icon.setDragCrossAnchor(Icon.getDefaultIcon().getDragCrossAnchor());
			icon.setIconAnchor(Icon.getDefaultIcon().getIconAnchor());
			if (!p.getImageURL().equals("<none>")) {
				icon.setImageURL(p.getImageURL());
			} else {
				if (p.isCurrentPlayer())
					icon.setImageURL("Images/sikh_disabled.png");
				else
					icon.setImageURL("Images/symbol_inter.png");
			}			
			
			icon.setShadowURL("Images/shadow.png");			
			icon.setIconSize(Size.newInstance(35, 35));
						
			MarkerOptions m1o = MarkerOptions.newInstance();
	    	m1o.setTitle(p.getCharacterName() + " (" + p.getNickName() + ")");
	    	m1o.setDraggable(p.isCurrentPlayer());
	    	m1o.setIcon(icon);
	    		    	
	    	final Marker playerMarker = new Marker(MapUtils.GetCurrentLocation(p),m1o);
	    	
	    	if (p.isCurrentPlayer()) {
	    		currentplayerMarker = playerMarker;
		    	playerMarker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
					public void onDragEnd(MarkerDragEndEvent event) {
						
						playerMarker.setImage("Images/clock.png");
						
						if (playerInfo.getOngoingEspionage().size() > 0L) {
							if (!Window.confirm("Moving will cancel ongoing espionage, are you sure?")) {
								return;
							}
						}
						
						if (playerInfo.getOngoingEspionage().size() > 0L) {
							campaignService.CancelEspionage(new AsyncCallback<Void>() {
								public void onFailure(Throwable error) {
				    				handleError(error);
				    			}
				    			public void onSuccess(Void ignore) {
				    				for (JobDTO job : playerInfo.getOngoingEspionage()) {
				    					job.setStatus("Canceled");
				    				}
				    			}
							});	
						}
						
						final LatLng loc = MapUtils.GetCurrentLocation(playerInfo);
						final double lat = event.getSender().getLatLng().getLatitude();
						final double lng = event.getSender().getLatLng().getLongitude();
						LatLng start = LatLng.newInstance(loc.getLatitude(), loc.getLongitude());
						LatLng end = LatLng.newInstance(lat, lng);
						final double miles = start.distanceFrom(end) * PlayerDTO.MILES_TO_LATLONG;
						campaignService.UpdateArmyDestination(playerInfo.getEmailAddress(), loc.getLatitude(), loc.getLongitude(), lat, lng, miles, new AsyncCallback<Void>() {
							public void onFailure(Throwable error) {
			    				handleError(error);
			    			}
			    			public void onSuccess(Void ignore) {
			    				playerInfo.setOriginLatitude(loc.getLatitude());
			    				playerInfo.setOriginLongitude(loc.getLongitude());
			    				playerInfo.setDestLatitude(lat);
			    				playerInfo.setDestLongitude(lng);
			    				playerInfo.setMilesToTravel(miles);
			    				playerInfo.setMoveStart(new Date());
			    				UpdatePlayerMarker();
			    			}
						});		
					}
				});
		    }
	    	playerMarker.addMarkerClickHandler(new MarkerClickHandler() {				
				@Override
				public void onClick(MarkerClickEvent event) {
					mainPage.centerPanel.clear();
		    		CharacterScreen form = new CharacterScreen(finalThis, p, playerInfo.isAdmin());
		    		mainPage.centerPanel.add(form);
		    	}
			});
	    	
	    	map.addOverlay(playerMarker);    	
	    	playerMarker.setDraggingEnabled(p.isCurrentPlayer());
		}
    	
    	map.panTo(MapUtils.GetCurrentLocation(playerInfo));
    	
    	UpdatePlayerMarker();
	}
	
	public void UpdatePlayerMarker() {
		
		if (currentplayerMarker == null) return;
		
		currentplayerMarker.setLatLng(MapUtils.GetCurrentLocation(playerInfo));
		if (!playerInfo.getImageURL().equals("<none>")) {
			currentplayerMarker.setImage(playerInfo.getImageURL());
		} else {
			currentplayerMarker.setImage("Images/sikh_disabled.png");
		}
		
		NumberFormat fmt = NumberFormat.getFormat("0");
		int secondsToDest = (int)(MapUtils.getSecondsToTravel(playerInfo) - MapUtils.getSecondsTraveledSoFar(playerInfo));
		
		if (secondsToDest <= 0) {
			if (playerDestMarker != null) {
				map.removeOverlay(playerDestMarker);
				playerDestMarker = null;
			}
			if (playerDestText != null) {
				map.removeOverlay(playerDestText);
				playerDestText = null;
			}
			if (playerInfo.getMilesToTravel() > 0) {
				campaignService.UpdateArmyDestination(playerInfo.getEmailAddress(), playerInfo.getDestLatitude(), playerInfo.getDestLongitude(), playerInfo.getDestLatitude(), playerInfo.getDestLongitude(), 0, new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				playerInfo.setOriginLatitude(playerInfo.getDestLatitude());
	    				playerInfo.setOriginLongitude(playerInfo.getDestLongitude());;
	    				playerInfo.setMilesToTravel(0);
	    				playerInfo.setMoveStart(new Date());
	    				UpdatePlayerMarker();
	    			}
				});
			}
		} else {
			if (playerDestMarker == null) {
				Icon icon = Icon.newInstance();
				icon.setDragCrossAnchor(Icon.getDefaultIcon().getDragCrossAnchor());
				icon.setIconAnchor(Icon.getDefaultIcon().getIconAnchor());
				icon.setImageURL("Images/sikh_used.png");
				icon.setShadowURL("Images/shadow.png");
											
				MarkerOptions m1o = MarkerOptions.newInstance();
		    	m1o.setIcon(icon);
		    		    	
		    	playerDestMarker = new Marker(MapUtils.GetDestination(playerInfo),m1o);
		    	map.addOverlay(playerDestMarker);
			}
			if (playerDestText == null) {
				playerDestText = new TextOverlay(MapUtils.GetDestination(playerInfo), "thinking...");
				map.addOverlay(playerDestText);
			}
			playerDestMarker.setLatLng(MapUtils.GetDestination(playerInfo));
			playerDestText.setLatLng(MapUtils.GetDestination(playerInfo));
			
			int days = secondsToDest/86400;
			int remainder = secondsToDest%86400;
			int hours = remainder / 3600;
			remainder = remainder % 3600;
			int minutes = remainder / 60;
			int seconds = remainder % 60;
			String out = "ETA - " + fmt.format(days) + ":" + fmt.format(hours) + ":" + fmt.format(minutes) + ":" + fmt.format(seconds);
			playerDestText.setText(out);
		}		
	}

	private void mapTutorial() {
								
		String html = "<b>World Map - Army icons</b>";
		html += "<BR><BR>";
	    html += "This icon represents your main army, which is currently your only army and is not much of one. (it currently only has you in it)  You can hover over an army icon to see the units in it.";
	    html += "<BR><BR>";
	    html += "&nbsp &nbsp &nbsp Moving Armies - By dragging and dropping an army icon you can set a move order for that it. It will move over the course of real-world time. Armies move about 50 miles a day.";
	    HTML message = new HTML(html);
	    
	    map.getInfoWindow().open(MapUtils.GetCurrentLocation(playerInfo), new InfoWindowContent(message));
	    map.addInfoWindowBeforeCloseHandler(new MapInfoWindowBeforeCloseHandler() {
	    	@Override
			public void onInfoWindowBeforeClose(MapInfoWindowBeforeCloseEvent event) {
//	    		map.removeInfoWindowBeforeCloseHandler(this);
//	    		LatLng point = CreateForageResource();
//	    		
//	    		String forageString = "<b>World Map - Foraging</b>";
//	    		forageString += "<BR><BR>";
//	    		forageString += "As your army moves it will come across resources that you can gather up. Green icons like this represent those resources, click on the icon to pick it up.";
//	    		forageString += "<BR><BR>";
//	    	    HTML forageMessage = new HTML(forageString);
//	    	    
//	    	    map.getInfoWindow().open(point, new InfoWindowContent(forageMessage));
//	    	    map.addInfoWindowBeforeCloseHandler(new MapInfoWindowBeforeCloseHandler() {
//	    	    	@Override
//	    			public void onInfoWindowBeforeClose(MapInfoWindowBeforeCloseEvent event) {
	    	    		map.removeInfoWindowBeforeCloseHandler(this);
	    	    		
	    	    		LoadCityMarkers();
	    	    		String cityString = "<b>World Map - Cites</b>";
	    	    		cityString += "<BR><BR>";
	    	    		cityString += "When you have an army near a city, you'll see icons for city options. You can do jobs for the local Lord to gain favor and gold, you can use espionage to gain leverage on the local Lord, and you can hire the mercenaries available there.";
	    	    		cityString += "<BR><BR>";
	    	    	    HTML cityMessage = new HTML(cityString);
	    	    	    
	    	    	    map.getInfoWindow().open(MapUtils.GetCurrentLocation(playerInfo), new InfoWindowContent(cityMessage));
	    	    	    map.addInfoWindowBeforeCloseHandler(new MapInfoWindowBeforeCloseHandler() {
	    	    	    	@Override
	    	    			public void onInfoWindowBeforeClose(MapInfoWindowBeforeCloseEvent event) {
	    	    	    		map.removeInfoWindowBeforeCloseHandler(this);
	    	    	    		campaignService.SetDoneTutorial("Map", new AsyncCallback<Void>() {
	    	    					public void onFailure(Throwable error) {
	    	    	    				handleError(error);
	    	    	    			}
	    	    	    			public void onSuccess(Void ignore) {
	    	    	    				playerInfo.setDoneMapTutorial(true);
	    	    	    			}
	    	    				});
	    	    	    	}
	    	    	    });
//	    	    	}
//	    	    });	    		
			}
	    });
	}
		
/*	private LatLng CreateForageResource() {
				 
		LatLng playerLocation = MapUtils.GetCurrentLocation(playerInfo);
		LatLng point = LatLng.newInstance(playerLocation.getLatitude()-.5, playerLocation.getLongitude()+.5);
		
		Icon icon = Icon.newInstance();
		icon.setDragCrossAnchor(Icon.getDefaultIcon().getDragCrossAnchor());
		icon.setIconAnchor(Icon.getDefaultIcon().getIconAnchor());		
		String iconName = "Bread";
		icon.setImageURL("Images/" + iconName + ".png");
		icon.setShadowURL("Images/shadow.png");
		
		MarkerOptions m1o = MarkerOptions.newInstance();
    	m1o.setTitle(iconName);
    	m1o.setIcon(icon);
    	
    	final Marker mark = new Marker(point,m1o);
    	
    	mark.addMarkerClickHandler(new MarkerClickHandler() {			
			@Override
			public void onClick(MarkerClickEvent event) {
				mark.setImage("Images/clock.png");
				mark.removeMarkerClickHandler(this);
				
				campaignService.Forage(new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				ResourceAmountDTO prc = playerInfo.getResource("Food");
	    				prc.setAmount(prc.getAmount()+10L); 				
	    			}
				});
				
				map.removeOverlay(mark);
			}
		}); 		
    	
    	map.addOverlay(mark);	
    	
    	return point;
	}*/
	
	private void LoadCityMarkers() {
		
		campaignService.GetCities(new AsyncCallback<CityDTO[]>() {
			public void onFailure(Throwable error) {
	    		handleError(error);
	    	}

	    	public void onSuccess(CityDTO[] result) {
	    		Cities = result;
	    		for (CityDTO city : result) {
	    			displayCityOptions(city);
	    		}
	    	}    	
		});
	}
	
	private void mapClicked(MapClickEvent e) {

		//Overlay overlay = e.getOverlay();
        //if (overlay != null ) return;
		
		//MapWidget sender = e.getSender();
        LatLng point = e.getLatLng();
      
        if (isAddingCity) {
        	final CityDTO city = new CityDTO();
        	String name = Window.prompt("Name", "");
        	city.setName(name);
        	String faction = Window.prompt("Faction", "Khador");
        	city.setFaction(faction); 
        	city.setLatitude(point.getLatitude());
        	city.setLongitude(point.getLongitude());
        	campaignService.AddCity(city, new AsyncCallback<Long>() {
        		public void onFailure(Throwable error) {
    				handleError(error);
    			}
    			public void onSuccess(Long id) {
    				city.setCityId(id);
    				displayCityOptions(city);
    			}
			});
        	
        	isAddingCity = false;
        } 
	}

	private void displayCityOptions(final CityDTO city) {
		
		final CampaignManager mainThis = this;
		
		showCityOptionMarker(1, 4, "Information", city, "Images/information.png", new MarkerClickHandler() {			
			@Override
			public void onClick(MarkerClickEvent event) {
				String html = "<b>"+city.getName() + ": " + city.getFaction()+"</b><BR>";
				html += "<hr/>";
				PlayerCityDTO pCity = playerInfo.getCity(city.getName());
				html += "<table><tr><td>Favor:</td><td>"+pCity.getFavor().toString()+"</td><td>Leverage:</td><td>"+pCity.getLeverage().toString()+"</td></tr></table>";
				html += "<hr/>";
				for (ResourceAmountDTO cr : city.getRelations()) {
					html += "<table><tr><td>Relationship with "+cr.getResource()+"</td><td>:</td><td>"+cr.getAmount().toString()+"</td></tr></table>";
				}
				HTML message = new HTML(html);
				map.getInfoWindow().open(city.GetLocation(), new InfoWindowContent(message));
			}
		});
		
		LatLng playerPoint = MapUtils.GetCurrentLocation(playerInfo);
		LatLng cityPoint = LatLng.newInstance(city.getLatitude(), city.getLongitude());
		double dist = playerPoint.distanceFrom(cityPoint);
	    dist = dist * PlayerDTO.MILES_TO_LATLONG;
	    if (dist <= PlayerDTO.FORAGE_MILES){
	    	    
			showCityOptionMarker(2, 4, "Jobs", city, "Images/text.png", new MarkerClickHandler() {			
				@Override
				public void onClick(MarkerClickEvent event) {
					PlayerCityDTO pc = playerInfo.getCity(city.getName());
					if (pc.getFavor() > -5) {
						mainPage.centerPanel.clear();				
						AvailableJobsForm form = new AvailableJobsForm(city.getName(), mainThis, playerInfo);
						mainPage.centerPanel.add(form);
						if (!playerInfo.isDoneJobTutorial()) {
							showJobTutorialDialog();
						}
					} else {
						Window.alert("You are not welcome here!");
					}
				}
			});
			
			showCityOptionMarker(3, 4, "Espionage", city, "Images/hats.png", new MarkerClickHandler() {			
				@Override
				public void onClick(MarkerClickEvent event) {
					mainPage.centerPanel.clear();				
					EspionageForm form = new EspionageForm(city.getName(), mainThis, playerInfo);
					mainPage.centerPanel.add(form);
					if (!playerInfo.isDoneEspionageTutorial()) {
						showEspionageTutorialDialog();
					}
				}
			});
			
			showCityOptionMarker(4, 4, "Hire", city, "Images/contract.png", new MarkerClickHandler() {			
				@Override
				public void onClick(MarkerClickEvent event) {
					PlayerCityDTO pc = playerInfo.getCity(city.getName());
					if (pc.getFavor() > -5) {
						mainPage.centerPanel.clear();				
						BuyUnitsForm form = new BuyUnitsForm(city, mainThis, playerInfo);
						mainPage.centerPanel.add(form);
						if (!playerInfo.isDoneHireTutorial()) {
							showHireTutorialDialog();
						}
					} else {
						Window.alert("You are not welcome here!");
					}
				}
			});	
	    }
	}
	private void showCityOptionMarker(int position, int total, String title, final CityDTO city, String image, MarkerClickHandler clickHandler) {
				
		double x = Math.sin((2*position*Math.PI)/total);
		x = x * .75;
		double y = Math.cos((2*position*Math.PI)/total);
		LatLng p =  LatLng.newInstance(city.GetLocation().getLatitude() + x, city.GetLocation().getLongitude() + y);
					
		Icon icon = Icon.newInstance();
		icon.setDragCrossAnchor(Icon.getDefaultIcon().getDragCrossAnchor());
		icon.setIconAnchor(Icon.getDefaultIcon().getIconAnchor());
		icon.setImageURL(image);
		icon.setShadowURL("Images/shadow.png");
		
		MarkerOptions m1o = MarkerOptions.newInstance();
    	m1o.setTitle(title);
    	m1o.setDraggable(playerInfo.isAdmin());
    	m1o.setIcon(icon);
    	
    	Marker mark = new Marker(p,m1o);
    	
    	mark.addMarkerDragEndHandler(new MarkerDragEndHandler() {
			public void onDragEnd(MarkerDragEndEvent event) {
				double lat = event.getSender().getLatLng().getLatitude();
				double lng = event.getSender().getLatLng().getLongitude();
				campaignService.UpdateCityLocation(city.getCityId(), lat, lng, new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				//the marker is already moved....
	    			}
				});				
			}
		});
    	
    	mark.addMarkerClickHandler(clickHandler);
    	  		    	
    	map.addOverlay(mark);    	
    	mark.setDraggingEnabled(playerInfo.isAdmin());		
	}
	
	private void showJobTutorialDialog() {
		
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
		dialogbox.setText("Jobs");
	    
	    String html = "<BR>Jobs have specific types with set rewards based on their difficulty. The story behind why you're doing it and/or why someone wants it done is up to you to invent. To take on a job, you must write a description of the story behind the job.  You can make it as short as you want, but entertaining, in-context stories that the rest of the players will enjoy will earn you valuable Narration Points, which allow you to advance your character.<BR>";
	    HTML message = new HTML(html);
	    
	    final Button button = new Button("Next");
	    button.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	button.setEnabled(false);
	        	button.setText("Updating...");
	        	campaignService.SetDoneTutorial("Job", new AsyncCallback<Void>() {
	    			public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				playerInfo.setDoneJobTutorial(true);	    				
	    				dialogbox.hide();
	    			}
	    		});	        	
	        }
        });
	    SimplePanel holder = new SimplePanel();
	    holder.add(button);
	    DialogBoxContents.add(message);
	    DialogBoxContents.add(holder);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();		
	}
	private void showEspionageTutorialDialog() {
		
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
		dialogbox.setText("Espionage");
	    
	    String html = "<BR>Espionage attempts have specific types with set rewards based on their difficulty. The story behind what you do, what you learn and who you coerce is up to you to invent. To attempt espionage, you must write a description of the story behind the attempt.  You can make it as short as you want, but entertaining, in-context stories that the rest of the players will enjoy will earn you valuable Narration Points, which allow you to advance your character.<BR>";
	    html += "<BR>All espionage attempts take 48 hours per level to complete and can be completed in the 'Current Activities' screen.<BR>";
	    HTML message = new HTML(html);
	    
	    final Button button = new Button("Next");
	    button.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	button.setEnabled(false);
	        	button.setText("Updating...");
	        	campaignService.SetDoneTutorial("Espionage", new AsyncCallback<Void>() {
	    			public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				playerInfo.setDoneEspionageTutorial(true);	    				
	    				dialogbox.hide();
	    			}
	    		});	        	
	        }
        });
	    SimplePanel holder = new SimplePanel();
	    holder.add(button);
	    DialogBoxContents.add(message);
	    DialogBoxContents.add(holder);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();		
	}
	private void showHireTutorialDialog() {
		
		final DialogBox dialogbox = new DialogBox(false);
		dialogbox.setWidth("800px");
		VerticalPanel DialogBoxContents = new VerticalPanel();
		dialogbox.setText("Hiring");
	    
	    String html = "<BR>You can recruit the units available from this city. If you are a member of the faction this city is in you can recruit faction units, otherwise you can hire mercs.<BR>";
	    HTML message = new HTML(html);
	    
	    final Button button = new Button("Next");
	    button.addClickHandler(new ClickHandler() {
	        public void onClick(ClickEvent event) {
	        	button.setEnabled(false);
	        	button.setText("Updating...");
	        	campaignService.SetDoneTutorial("Hire", new AsyncCallback<Void>() {
	    			public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				playerInfo.setDoneHireTutorial(true);	    				
	    				dialogbox.hide();
	    			}
	    		});	        	
	        }
        });
	    SimplePanel holder = new SimplePanel();
	    holder.add(button);
	    DialogBoxContents.add(message);
	    DialogBoxContents.add(holder);
	    dialogbox.setWidget(DialogBoxContents);
	    dialogbox.center();		
	}
	
	public void showMap() {
		mainPage.centerPanel.clear();
		mainPage.centerPanel.add(map);
	}
	
	public void showCharacterScreen() {
		mainPage.centerPanel.clear();
		CharacterScreen form = new CharacterScreen(this, playerInfo, playerInfo.isAdmin());
		mainPage.centerPanel.add(form);
	}
	
	public void showActivities() {
		mainPage.centerPanel.clear();
		ActivitiesForm form = new ActivitiesForm(this, playerInfo);
		mainPage.centerPanel.add(form);
	}
	
	public void showUnits() {
		mainPage.centerPanel.clear();
		ArmyFrom form = new ArmyFrom(this, playerInfo);
		mainPage.centerPanel.add(form);
	}
	
	public void SaveNewUnitType(final UnitTypeDTO unitType) {
		/*campaignService.addUnitType(unitType, new AsyncCallback<Long>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(Long id) {
				unitType.setId(id);
				//DisplayUnitTypeRow(unitType);
			}
		});*/
		mainPage.centerPanel.clear();
		mainPage.centerPanel.add(map);
	}
	
	public String CostText(List<ResourceAmountDTO> cost) {
		String costStr = "";
		String weeklyCost = "";
		for (ResourceAmountDTO rac : cost) {
			if (rac.getAmount() > 0){
				costStr += rac.getResource() + ":" + rac.getAmount() + "; ";
				weeklyCost += rac.getResource() + ":" + rac.getAmount()/2+"/week;";
			}
		}
		if (!costStr.isEmpty())
			return costStr+" and "+weeklyCost;
		else
			return "";
	}
	
/*	private void loadPlayerList() {
		
		mainPage.messageToText.addItem("Scout");
		mainPage.messageToText.addItem("My Units");
		mainPage.messageToText.addItem("All Players");

		campaignService.getPlayers(new AsyncCallback<PlayerClient[]>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(PlayerClient[] p) {
				
				players = p;
				
				for (PlayerClient player : players) {
					mainPage.messageToText.addItem(player.getEmailAddress());
				}
				addPlayerMarkers();				
			}
		});
	}

	public void DisplayPlayerInfo() {		
				
		mainPage.headerTable.getRowFormatter().addStyleName(0, "watchListHeader");
		mainPage.headerTable.getRowFormatter().addStyleName(1, "watchListHeader");
		mainPage.headerTable.addStyleName("watchList");
		
		mainPage.headerTable.setText(0, 0, "Level: " + playerInfo.getLevel());		
		mainPage.headerTable.setText(0, 1, "Total Points worth of units you have right now: " + playerInfo.getPointsSpent());
		
		mainPage.headerTable.setText(1, 0, "Biggest unit you can build: " + PlayerClient.getUnitCostLimit(playerInfo.getLevel()));		
		mainPage.headerTable.setText(1, 1, "Total Points worth of units you can have: " + PlayerClient.getPointLimit(playerInfo.getLevel()));
		
		
	}
				
	private void loadMessageData() {
		SetupMessageTable();
		campaignService.getInbox(new AsyncCallback<InboxMessageClient[]>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(InboxMessageClient[] messages) {
				displayMessageRows(messages);
			}
	});
	}
	private void SetupMessageTable() {
		
		mainPage.messageTable.setText(0, 0, "From");
		mainPage.messageTable.setText(0, 1, "To");
		mainPage.messageTable.setText(0, 2, "Message");
		
		mainPage.messageTable.getRowFormatter().addStyleName(0, "watchListHeader");
		mainPage.messageTable.addStyleName("watchList");
	}	

	private void loadUnitData() {
		SetupUnitTable();
		campaignService.getUnits(new AsyncCallback<UnitClient[]>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(UnitClient[] units) {
				displayUnitRows(units);
			}
		});
	}
		
	//Regions
	private void loadRegions() {
		campaignService.getRegions(new AsyncCallback<RegionClient[]>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(RegionClient[] regions) {
				for (RegionClient r : regions) {
					displayRegion(r);
				}
			}
		});	
	}
	private void displayRegion(final RegionClient r) {
		
		boolean regionHarvestable = (r.getLastHarvestedDate()==null || CalendarUtil.getDaysBetween(r.getLastHarvestedDate(),  new Date()) >= 1);
				
		LatLng point = LatLng.newInstance(r.getLatitude(), r.getLongitude());
		
		int resourceCount = r.getResources().length;
		int i = 0;
		
		for (final String resource : r.getResources()) {
			
			String iconName = getIconForResource(resource);
			
			double x = Math.sin((2*i*Math.PI)/resourceCount);
			double y = Math.abs(Math.cos((i*Math.PI)/resourceCount));
			Point p =  Point.newInstance((int)Math.round(x*23), (int)Math.round(y*40)); //Icon.getDefaultIcon().getDragCrossAnchor();
						
			Icon icon = Icon.newInstance();			
			icon.setIconAnchor(p); //Point.newInstance(p.getX()+(i*50), p.getY()));
			if (!r.getActive())
				icon.setImageURL("Images/" + iconName + "_disabled.png");
			else if (regionHarvestable)
				icon.setImageURL("Images/" + iconName + ".png");
			else 
				icon.setImageURL("Images/" + iconName + "_used.png");
			
			MarkerOptions m1o = MarkerOptions.newInstance();
	    	m1o.setTitle(resource);
	    	m1o.setDraggable(playerInfo.isAdmin());
	    	m1o.setIcon(icon);
	    	
	    	Marker mark = new Marker(point,m1o);
	    	
	    	r.markers.add(mark);
	    	
	    	mark.addMarkerDragEndHandler(new MarkerDragEndHandler() {
				public void onDragEnd(MarkerDragEndEvent event) {
					double lat = event.getSender().getLatLng().getLatitude();
					double lng = event.getSender().getLatLng().getLongitude();
					campaignService.UpdateRegionLocation(r.getRegionId(), lat, lng, new AsyncCallback<Void>() {
						public void onFailure(Throwable error) {
		    				handleError(error);
		    			}
		    			public void onSuccess(Void ignore) {
		    				//the marker is already moved....
		    			}
					});
				}
			});
	    	
	    	if (r.getActive() && regionHarvestable) {
	    		mark.addMarkerClickHandler(new MarkerClickHandler() {			
					@Override
					public void onClick(MarkerClickEvent event) {
						for (Marker m : r.markers) {
							m.setImage("Images/clock.png");
							m.removeMarkerClickHandler(this);	
						}					
						campaignService.HarvestRegion(r, resource, new AsyncCallback<Void>() {
							public void onFailure(Throwable error) {
			    				handleError(error);
			    			}
			    			public void onSuccess(Void ignore) {
			    				for (Marker m : r.markers) {
			    					String s = m.getIcon().getImageURL();
			    					String s2 = s.replace(".png", "_used.png");
									m.setImage(s2);
								}
			    				for (ResourceAmountClient prc : playerInfo.getResources()) {
			    					if (prc.getResource().equals(resource)) {
			    						prc.setAmount(prc.getAmount()+1L);
			    						if (prc.getResource().equalsIgnoreCase("Food")) {
			    							prc.setAmount(prc.getAmount() + 1L);
			    						}
			    					}			    					
			    				}
			    				DisplayPlayerInfo();			    				
			    			}
						});
					}
				});
	    	}   		
	    	
	    	map.addOverlay(mark);    	
	    	mark.setDraggingEnabled(playerInfo.isAdmin());
	    	
	    	i++;
		}
	}
	public void ShowAvailableJobsForm() {		
		AvailableJobsForm form = new AvailableJobsForm(this);
		mainPage.centerPanel.clear();
		mainPage.centerPanel.add(form);
	}
	public void SaveNewRegion(RegionClient region) {
		regionToAdd = region;
		addingRegion = true;
		mainPage.centerPanel.clear();
		mainPage.centerPanel.add(map);
	}
	
	//Ma)p
	
	private void loadMarkers() {
		campaignService.getMarkers(new AsyncCallback<MapMarkerClient[]>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(MapMarkerClient[] markers) {
				for (MapMarkerClient m : markers) {
					displayMarker(m);
				}
			}
		});
	}
	private void displayMarker(final MapMarkerClient m) {
		
		LatLng point = LatLng.newInstance(m.getLatitude(), m.getLongitude());
		
		MarkerOptions m1o = MarkerOptions.newInstance();
    	m1o.setTitle(m.getText());
    	m1o.setDraggable(true);
    	
    	Marker mark = new Marker(point,m1o);
    	
    	mark.addMarkerDragEndHandler(new MarkerDragEndHandler() {
			public void onDragEnd(MarkerDragEndEvent event) {
				double lat = event.getSender().getLatLng().getLatitude();
				double lng = event.getSender().getLatLng().getLongitude();
				campaignService.UpdateMarkerLocation(m.getId(), lat, lng, new AsyncCallback<Void>() {
					public void onFailure(Throwable error) {
	    				handleError(error);
	    			}
	    			public void onSuccess(Void ignore) {
	    				//the marker is already moved....
	    			}
				});				
			}
		});
    	mark.addMarkerDoubleClickHandler(new MarkerDoubleClickHandler() {			
			@Override
			public void onDoubleClick(final MarkerDoubleClickEvent event) {
				if (Window.confirm("Delete this marker?")) {
					campaignService.removeMarker(m.getId(), new AsyncCallback<Void>() {
						public void onFailure(Throwable error) {
		    				handleError(error);
		    			}
		    			public void onSuccess(Void ignore) {
		    				map.removeOverlay(event.getSender());		    				
		    			}
					});
				}
			}
		});
    	
    	map.addOverlay(mark);    	
    	mark.setDraggingEnabled(true);
	}
	private void MeasureRuler() {
		if (rulerMarker1 != null && rulerMarker2 != null ) {
			
			NumberFormat fmt = NumberFormat.getFormat("0");
			
		    double dist = rulerMarker1.getPoint().distanceFrom(rulerMarker2.getPoint());
		    dist = dist * 0.0001478;
		    label1.setText(fmt.format(dist) + " Miles");
		    if(poly != null )
		    	map.removeOverlay(poly);
		    poly = new Polyline(new LatLng[]{rulerMarker1.getPoint(),rulerMarker2.getPoint()},"#FFFF00", 8, 1);
		    map.addOverlay(poly);
		}
	}
	private void ClearRuler() {
		map.removeOverlay(poly);
	    map.removeOverlay(rulerMarker1);
	    map.removeOverlay(rulerMarker2);
	    label1.setText(null);
	    haveRuler = false;
	    mainPage.useRuler.setText("Use Ruler");
	}
	public void AddMarker() {
		addingMarker = true;
	}
	public void UseRuler() {
		if (haveRuler)
			ClearRuler();
		else {
			addingRuler = true;
			mainPage.useRuler.setText("Click the map...");
		}			
	}
	private void mapClicked(MapClickEvent e) {
		MapWidget sender = e.getSender();
        Overlay overlay = e.getOverlay();
        LatLng point = e.getLatLng();
        
        if (overlay != null ) return;
      
        if (addingMarker) {
        	final MapMarkerClient m = new MapMarkerClient();
        	m.setText(mainPage.mapMarkerText.getText());
        	m.setLatitude(point.getLatitude());
        	m.setLongitude(point.getLongitude());
        	campaignService.addMarker(m, new AsyncCallback<Long>() {
        		public void onFailure(Throwable error) {
    				handleError(error);
    			}
    			public void onSuccess(Long id) {
    				m.setId(id);
    				displayMarker(m);
    				mainPage.mapMarkerText.setText("");
    			}
			});
        	
        	addingMarker = false;        	
        	
        } else if (addingRuler) {                
        	MarkerOptions m1o = MarkerOptions.newInstance();
        	m1o.setDraggable(true);
        	rulerMarker1 = new Marker(point,m1o);		            	
            map.addOverlay(rulerMarker1);
            rulerMarker1.setDraggingEnabled(true);		                
            rulerMarker1.addMarkerDragHandler(new MarkerDragHandler() {							
				@Override
				public void onDrag(MarkerDragEvent event) {
					MeasureRuler();
				}
			});
            rulerMarker1.addMarkerDoubleClickHandler(new MarkerDoubleClickHandler() {							
				@Override
				public void onDoubleClick(MarkerDoubleClickEvent event) {
					ClearRuler();
				}
			});
            
            MarkerOptions m2o = MarkerOptions.newInstance();
        	m2o.setDraggable(true);
        	rulerMarker2 = new Marker(point,m2o);
            map.addOverlay(rulerMarker2);
            rulerMarker2.setDraggingEnabled(true);
            rulerMarker2.addMarkerDragHandler(new MarkerDragHandler() {							
				@Override
				public void onDrag(MarkerDragEvent event) {
					MeasureRuler();
				}
			});
            rulerMarker2.addMarkerDoubleClickHandler(new MarkerDoubleClickHandler() {							
				@Override
				public void onDoubleClick(MarkerDoubleClickEvent event) {
					ClearRuler();
				}
			});
            
            addingRuler = false;
            haveRuler = true;
            mainPage.useRuler.setText("Remove Ruler");
        } else if (addingRegion) {
        	regionToAdd.setLatitude(point.getLatitude());
        	regionToAdd.setLongitude(point.getLongitude());     	
        	
        	campaignService.addRegion(regionToAdd, new AsyncCallback<Long>() {
        		public void onFailure(Throwable error) {
    				handleError(error);
    			}
    			public void onSuccess(Long id) {
    				regionToAdd.setRegionId(id);
    				displayRegion(regionToAdd);
    				mainPage.mapMarkerText.setText("");
    			}
			});
        	
        	addingRegion = false;
        }
	}
	
	private void addPlayerMarkers() {
		if (addedPlayerMarkers) return;
		
		if (map == null || players == null) return;
		
		addedPlayerMarkers = true;
		
		for (final PlayerClient player : players) {
			LatLng point  = LatLng.newInstance(player.getLatitude(), player.getLongitude());
			
			Icon icon = Icon.newInstance();
			icon.setDragCrossAnchor(Icon.getDefaultIcon().getDragCrossAnchor());
			icon.setIconAnchor(Icon.getDefaultIcon().getIconAnchor());
			icon.setImageURL("http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png");
						
			MarkerOptions m1o = MarkerOptions.newInstance();
	    	m1o.setTitle(player.getNickname() + " (" + player.getEmailAddress() + ")");
	    	m1o.setDraggable(playerInfo.isAdmin());
	    	m1o.setIcon(icon);
	    		    	
	    	Marker mark = new Marker(point,m1o);
	    	
	    	mark.addMarkerDragEndHandler(new MarkerDragEndHandler() {
				public void onDragEnd(MarkerDragEndEvent event) {
					double lat = event.getSender().getLatLng().getLatitude();
					double lng = event.getSender().getLatLng().getLongitude();
					campaignService.updatePlayerLocation(player.getEmailAddress(), lat, lng, new AsyncCallback<Void>() {
						public void onFailure(Throwable error) {
		    				handleError(error);
		    			}
		    			public void onSuccess(Void ignore) {
		    				//the marker is already moved....
		    			}
					});				
				}
			});
	    	
	    	map.addOverlay(mark);    	
	    	mark.setDraggingEnabled(playerInfo.isAdmin());
		}
	}
	
	//Messages
	public void AddMessage(final InboxMessageClient message) {
		campaignService.addMessage(message, new AsyncCallback<Long>() {
			public void onFailure(Throwable error) {
				handleError(error);
			}
			public void onSuccess(Long id) {
				message.setId(id);
				displayMessageRow(message);
			}
		});
	}
	private void displayMessageRows(InboxMessageClient[] messages) {
		for (InboxMessageClient message : messages) {
			displayMessageRow(message);
		}
	}
	private void displayMessageRow(final InboxMessageClient message) {

		int row = mainPage.messageTable.getRowCount();

		mainPage.messageTable.setText(row, 0, message.getFrom());
		mainPage.messageTable.setText(row, 1, message.getTo());
		mainPage.messageTable.setText(row, 2, message.getText());
		mainPage.messageTable.setText(row, 3, DateTimeFormat.getShortDateFormat().format(message.getCreateDate()));		
	}
	
	//Units
	
	
	
	public void ShowMap() {
		mainPage.centerPanel.clear();
		VerticalPanel v = new VerticalPanel();
    	label1 = new Label();
    	v.add(label1);
    	v.add(map);
    	mainPage.centerPanel.add(v);
	}
	
	
	
	//Unit Types
	public void ShowAddUnitTypeForm() {
		AddUnitTypeForm form = new AddUnitTypeForm(this);
		mainPage.centerPanel.clear();
		mainPage.centerPanel.add(form);
	}
	
	public void ShowBuyUnitsForm() {
		BuyUnitsForm form = new BuyUnitsForm(this);
		
		if (playerInfo.isAdmin())
			form.addUnitTypeButton.setVisible(true);

		mainPage.centerPanel.clear();
		mainPage.centerPanel.add(form);
	}
	 	
	private String getIconForResource(String resource) {
		if (resource.equals("Food"))
			return "bread";
		else if (resource.equals("Coal"))
			return "mine";
		else if (resource.equals("Water"))
			return "river";
		else if (resource.equals("Hay"))
			return "haybale";
		else if (resource.equals("Arcane"))
			return "sikh";
		else if (resource.equals("Gold"))
			return "coins";
		else if (resource.equals("Blasting Powder"))
			return "fireworks";
		else if (resource.equals("Wool Cloth"))
			return "textiles";
		else if (resource.equals("GunPowder"))
			return "blast";
		
		return "bread";
	}
*/	

	public void handleError(Throwable error) {
		
		if (error instanceof NotLoggedInException) {
			if (playerInfo == null) {
				Window.alert("Handling error, but playerinfo is null: " + error.getMessage());
				return;
			} else {
				Window.Location.replace(playerInfo.getLogoutUrl());
				return;
			}				
		}
		
		if (playerInfo == null) {
			Window.alert("Handling error, but playerinfo is null: " + error.getMessage());
		} else if (playerInfo.isAdmin())
			Window.alert(error.getMessage());
		else
			Window.alert("There was an error, you should refresh the page.");
	}
} 